// system.h 
//	All global variables used in Nachos are defined here.
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation 
// of liability and disclaimer of warranty provisions.

#ifndef SYSTEM_H
#define SYSTEM_H

#include "copyright.h"
#include "utility.h"
#include "thread.h"
#include "scheduler.h"
#include "interrupt.h"
#include "stats.h"
#include "timer.h"
#include "synch.h"	//By OceanMaster

//--------------Project3---------------
#ifdef USE_TLB
#include "mmu.h"	
#endif
//----------------end------------------


// Initialization and cleanup routines
extern void Initialize(int argc, char **argv); 	// Initialization,
						// called before anything else
extern void Cleanup();				// Cleanup, called when
						// Nachos is done.

extern Thread * currentThread;			// the thread holding the CPU
extern Thread * threadToBeDestroyed;  		// the thread that just finished
extern Scheduler *scheduler;			// the ready list
extern Interrupt *interrupt;			// interrupt status
extern Statistics *stats;			// performance metrics
extern Timer *timer;				// the hardware alarm clock

#ifdef USER_PROGRAM
#include "machine.h"

#define LockTableSize 1024			//Size of Lock table
#define ConditionTableSize 1024			//Size of Condition Table
#define ProcessTableSize 512			//Size of Process Table

extern Machine* machine;			// user program memory and registers
//--------------------------
//Added in project2    Part1
//	Process Struct
//	Process Table
//	Process Management
//  	Thread Management
//	Function Stub for Fork and Exec
//--------------------------
extern Lock * deleteLock;			//the Lock to synchronize deletion from process table.

extern int ThreadIndex;				//Index for generated Thread, for identification


class KernelProcess
{
  public:
	KernelProcess(int id);
	~KernelProcess();
	
	void addCurrentThread();
	void deleteCurrentThread();

	Thread * GetThread(int threadId);
	int GetThreadNum();
	int GetActiveThreadNum();
	
	int AssignThreadId();			//IMPORTANT!! Caller has to explicitly call this to assign a thread Id for new thread
									//This should be done before Fork LoadUserFunction, to avoid race Condition

	int ProcessId;
 	AddrSpace * space;	
  private:

	Thread * * threadTable;

	int threadNum;		//living thread Num (Active + Sleeping)
		
	int nextThreadId;	//next Thread Id
	int threadTableSize;
	Lock * threadTableLock;
};

//int nextProcessId;					// Preserve spaceId
//int processNum;
//Lock * ProcessTableLock;
extern KernelProcess * * ProcessTable;

extern int AddProcess();
extern void DeleteProcess(int processId);
extern int GetProcessNum();
extern KernelProcess * GetProcess(int processId);

//Assumption: spaceId has been set by Forker
extern void LoadUserFunction(int VirtAddr);
extern void LoadUserProgram(int executable);
//extern void CleanUpAll();
//--------------------------
// Add end	       Part1
//--------------------------

//--------------------------
//Added in project2    Part2
//	MemoryMap
//	MemoryLock
//  KernelLock Struct
//  Lock table
//  KernelCondition Struct
//  Condition table
//  Address Space Table
//  Process table
//by OceanMaster
//--------------------------

//Memory Management

//BitMap * MemoryMap;				//Manage machine's Main memory pages
//Lock * MemoryLock;
extern int RequestMemoryPage();
extern void RecycleMemoryPage(int physicPage);

//Lock Management

struct KernelLock
{
	Lock * lock;
	//AddrSpace * address;	//Lock is a resource that related to a Process
	int processId;			
	//We now use processId to distinguish process, because we found sometimes address pointer may be reused by new process if former one has been recycled
	bool isDeleted;
	bool toBeDeleted;
};

//KernelLock * * LockTable;
//int nextLockIndex;
//Lock * LockTableLock;

extern int RegisterLock(Lock * lock);
extern void DeleteLock(int index);
extern void AcquireLock(int index);
extern void ReleaseLock(int index);

//Condition Management
struct KernelCondition
{
	Condition * condition;
	//AddrSpace * address;	//Condition is a resource that related to a Process
	int processId;
	bool isDeleted;
	bool toBeDeleted;
};

//KernelCondition * * ConditionTable;
//int nextConditionIndex;
//Lock * ConditionTableLock;

extern int RegisterCondition(Condition * condition);
extern void DeleteCondition(int cond_index);
extern void WaitCondition(int cond_index, int lock_index);
extern void SignalCondition(int cond_index,int lock_index);
extern void BroadcastCondition(int cond_index,int lock_index);
//--------------------------
//Add end	       Part2
//--------------------------
#endif

#ifdef FILESYS_NEEDED 		// FILESYS or FILESYS_STUB 
#include "filesys.h"
extern FileSystem  *fileSystem;
#endif

#ifdef FILESYS
#include "synchdisk.h"
extern SynchDisk   *synchDisk;
#endif

#ifdef NETWORK
#include "post.h"
extern PostOffice* postOffice;
extern int netname;
//Project4
extern int serverNum;
extern bool printLog;
#endif

#endif // SYSTEM_H
